import { RouteRecordRaw, RouteRecordNormalized, RouteRecordName } from 'vue-router'
import { IRootState } from '../index'
import { ActionTree, Module, MutationTree } from 'vuex'
import {
  ADD_CACHE_VIEW,
  ADD_VISITED_VIEW,
  CLEAR_CACHE_VIEW, DEL_ALL_VIEWS, DEL_ALL_VISITED_VIEWS,
  DEL_CACHE_VIEW, DEL_OTHER_VISITED_VIEWS,
  DEL_VISITED_VIEW
} from '@/store/modules/methods-type'

export interface RouteLocationWithFullPath extends RouteRecordNormalized {
  fullPath?: string
}

export interface ITagsViewState {
  visitedViews: RouteLocationWithFullPath[],
  cachedViews: RouteRecordName[]
}

const mutations: MutationTree<ITagsViewState> = {
  [ADD_VISITED_VIEW](state, view: RouteLocationWithFullPath) {
    const localIndex = state.visitedViews.findIndex(item => item.path === view.path)
    if ( localIndex !== - 1 ) return
    state.visitedViews.push(Object.assign({}, view, {
      title: view.meta?.title || 'tag-name'
    }))
  },
  [DEL_VISITED_VIEW](state, view: RouteLocationWithFullPath) {
    const localIndex = state.visitedViews.findIndex(item => item.path === view.path)
    if ( localIndex === - 1 ) return
    state.visitedViews.splice(localIndex, 1)
  },
  [ADD_CACHE_VIEW](state, view: RouteLocationWithFullPath) {
    if ( state.cachedViews.includes(view.name as string) || view.meta.noCache || typeof view.meta.noCache === 'undefined' ) return
    state.cachedViews.push(view.name as string)
  },
  [DEL_CACHE_VIEW](state, view: RouteLocationWithFullPath) {
    const localIndex = state.cachedViews.findIndex(name => view.name === name)
    if ( localIndex === - 1 ) return
    state.cachedViews.splice(localIndex, 1)
  },
  [CLEAR_CACHE_VIEW](state) {
    if ( state.cachedViews.length === 0 ) return
    state.cachedViews = []
  },
  [DEL_ALL_VISITED_VIEWS](state) {
    const affixTags = state.visitedViews.filter(item => item.meta && item.meta.affix)
    state.visitedViews = affixTags
  },
  [DEL_OTHER_VISITED_VIEWS](state, view: RouteLocationWithFullPath) {
    state.visitedViews = state.visitedViews.filter(tag => tag.meta.affix || (tag.path === view.path))
    state.cachedViews = state.cachedViews.filter(name => name !== view.name)
  }
}

const actions: ActionTree<ITagsViewState, IRootState> = {
  [ADD_VISITED_VIEW]({ commit, dispatch }, view: RouteLocationWithFullPath) {
    commit(ADD_VISITED_VIEW, view)
    dispatch(ADD_CACHE_VIEW, view)
  },
  [DEL_VISITED_VIEW]({ commit, dispatch }, view: RouteLocationWithFullPath) {
    return new Promise(resolve => {
      commit(DEL_VISITED_VIEW, view)
      dispatch(DEL_CACHE_VIEW, view)
      resolve(null)
    })
  },
  [ADD_CACHE_VIEW]({ commit }, view: RouteLocationWithFullPath) {
    commit(ADD_CACHE_VIEW, view)
  },
  [DEL_CACHE_VIEW]({ commit }, view: RouteLocationWithFullPath) {
    return new Promise(resolve => {
      commit(DEL_CACHE_VIEW, view)
      resolve(null)
    })
  },
  [CLEAR_CACHE_VIEW]({ commit }) {
    commit(CLEAR_CACHE_VIEW)
  },
  [DEL_ALL_VIEWS]({ dispatch, commit }) {
    return new Promise(resolve => {
      commit(DEL_ALL_VISITED_VIEWS)
      dispatch(CLEAR_CACHE_VIEW)
      resolve(null)
    })
  },
  [DEL_OTHER_VISITED_VIEWS]({ commit }, view: RouteLocationWithFullPath) {
    commit(DEL_OTHER_VISITED_VIEWS, view)
  }
}

const tagsView: Module<ITagsViewState, IRootState> = {
  namespaced: true,
  state: {
    visitedViews: [],
    cachedViews: []
  },
  actions,
  mutations
}

export default tagsView
